// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
use netstat2::{get_sockets_info, AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo};
use serde::{Deserialize, Serialize};
use std::process::Command;
use sysinfo::{Pid, PidExt, Process, ProcessExt, System, SystemExt};

#[derive(Serialize, Deserialize, Debug)]
pub struct PortProcess {
    pid: u32,
    port: u16,
    protocol: String,
    process_name: String,
    local_address: String,
    remote_address: String,
}

#[tauri::command]
fn get_port_info(port: Option<u16>) -> Result<Vec<PortProcess>, String> {
    let sockets = match get_sockets_info(
        AddressFamilyFlags::IPV4 | AddressFamilyFlags::IPV6,
        ProtocolFlags::TCP | ProtocolFlags::UDP,
    ) {
        Ok(sockets) => sockets,
        Err(e) => return Err(format!("获取套接字信息失败: {}", e)),
    };

    let mut system = System::new_all();
    system.refresh_all();
    
    let mut result = Vec::new();
    
    for socket in sockets {
        let local_port = match &socket.protocol_socket_info {
            ProtocolSocketInfo::Tcp(info) => info.local_port,
            ProtocolSocketInfo::Udp(info) => info.local_port,
        };
        
        // 如果指定了端口，则只返回匹配的端口信息
        if let Some(search_port) = port {
            if local_port != search_port {
                continue;
            }
        }
        
        let protocol = match &socket.protocol_socket_info {
            ProtocolSocketInfo::Tcp(_) => "TCP".to_string(),
            ProtocolSocketInfo::Udp(_) => "UDP".to_string(),
        };
        
        let local_addr = match &socket.protocol_socket_info {
            ProtocolSocketInfo::Tcp(info) => format!("{}:{}", info.local_addr, info.local_port),
            ProtocolSocketInfo::Udp(info) => format!("{}:{}", info.local_addr, info.local_port),
        };
        
        let remote_addr = match &socket.protocol_socket_info {
            ProtocolSocketInfo::Tcp(info) => format!("{}:{}", info.remote_addr, info.remote_port),
            ProtocolSocketInfo::Udp(_) => "".to_string(),
        };
        
        let process_name = if let Some(pid) = socket.associated_pids.first() {
            if let Some(process) = system.process(Pid::from_u32(*pid)) {
                process.name().to_string()
            } else {
                "未知".to_string()
            }
        } else {
            "未知".to_string()
        };
        
        if let Some(pid) = socket.associated_pids.first() {
            result.push(PortProcess {
                pid: *pid,
                port: local_port,
                protocol,
                process_name,
                local_address: local_addr,
                remote_address: remote_addr,
            });
        }
    }
    
    Ok(result)
}

#[tauri::command]
fn kill_process(pid: u32) -> Result<(), String> {
    let mut system = System::new_all();
    system.refresh_all();
    
    let process_pid = Pid::from_u32(pid);
    
    if system.process(process_pid).is_none() {
        return Err(format!("进程 {} 不存在", pid));
    }
    
    #[cfg(target_os = "windows")]
    {
        let status = Command::new("taskkill")
            .args(&["/F", "/PID", &pid.to_string()])
            .status();
            
        match status {
            Ok(exit_status) => {
                if exit_status.success() {
                    Ok(())
                } else {
                    Err(format!("无法终止进程 {}: 命令退出代码 {:?}", pid, exit_status.code()))
                }
            },
            Err(e) => Err(format!("无法终止进程 {}: {}", pid, e)),
        }
    }
    
    #[cfg(not(target_os = "windows"))]
    {
        let status = Command::new("kill")
            .args(&["-9", &pid.to_string()])
            .status();
            
        match status {
            Ok(exit_status) => {
                if exit_status.success() {
                    Ok(())
                } else {
                    Err(format!("无法终止进程 {}: 命令退出代码 {:?}", pid, exit_status.code()))
                }
            },
            Err(e) => Err(format!("无法终止进程 {}: {}", pid, e)),
        }
    }
}

#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

pub fn run() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet, get_port_info, kill_process])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
